package cn.tedu.carehome.foundation.service.impl;

import cn.tedu.carehome.foundation.ex.ServiceException;
import cn.tedu.carehome.foundation.mapper.OlderStaffMapper;
import cn.tedu.carehome.foundation.mapper.StaffMapper;
import cn.tedu.carehome.foundation.mapper.StaffRoleMapper;
import cn.tedu.carehome.foundation.pojo.dto.StaffAddNewDTO;
import cn.tedu.carehome.foundation.pojo.dto.StaffLoginDTO;
import cn.tedu.carehome.foundation.pojo.entity.Staff;
import cn.tedu.carehome.foundation.pojo.entity.StaffRole;
import cn.tedu.carehome.foundation.pojo.vo.StaffListItemVO;
import cn.tedu.carehome.foundation.pojo.vo.StaffStandardVO;
import cn.tedu.carehome.foundation.security.StaffDetails;
import cn.tedu.carehome.foundation.service.IStaffService;
import cn.tedu.carehome.foundation.web.ServiceCode;
import com.alibaba.fastjson.JSON;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 处理员工数据的业务实现类
 * @author 张子豪
 * @version 0.0.1
 */
@Service
@Slf4j
public class StaffServiceImpl implements IStaffService {
    @Value("${csmall.jwt.secret-key}")
    private String secretKey;
    @Value("${csmall.jwt.duration-in-minute}")
    private long durationInMinute;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private StaffMapper staffMapper;
    @Autowired
    private StaffRoleMapper staffRoleMapper;
    @Autowired
    private OlderStaffMapper olderStaffMaper;
    @Autowired
    private AuthenticationManager authenticationManager;

    public StaffServiceImpl() {
        log.debug("创建业务对象：StaffService");
    }

    //处理员工登录的业务方法
    @Override
    public String login(StaffLoginDTO staffLoginDTO) {
        log.debug("开始处理【员工登录】的业务，参数：{}", staffLoginDTO);
        UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(staffLoginDTO.getUsername(), staffLoginDTO.getPassword());
        Authentication authenticationResult = authenticationManager.authenticate(authentication);
        log.debug("认证通过，认证结果：{}", authenticationResult);
        log.debug("认证通过，认证结果中的当事人：{}", authenticationResult.getPrincipal());
        //将通过认证的管理员相关信息存入到JWT中
        //准备生成JWT的相关数据
        Date date = new Date(System.currentTimeMillis() + durationInMinute * 60 * 1000);
        StaffDetails principal = (StaffDetails) authenticationResult.getPrincipal();
        Map<String, Object> claims = new HashMap<>();
        claims.put("id", principal.getId());
        claims.put("username", principal.getUsername());
        Collection<GrantedAuthority> authorities = principal.getAuthorities();
        String authoritiesJsonString = JSON.toJSONString(authorities);
        claims.put("authoritiesJsonString", authoritiesJsonString);
        //生成JWT
        String jwt = Jwts.builder()
                //header
                .setHeaderParam("alg", "HS256")
                .setHeaderParam("typ", "JWT")
                //Payload
                .setClaims(claims)
                //Signature
                .setExpiration(date)
                .signWith(SignatureAlgorithm.HS256, secretKey)
                .compact();
        log.debug("返回JWT数据，JWT:{}", jwt);
        return jwt;
    }
    //添加员工帐号的业务方法
    @Override
    public void addNew(StaffAddNewDTO staffAddNewDTO) {
        log.debug("开始处理添加员工账号的业务");
        //检查角色Id的数组中是否包含一号角色
//        if (staffAddNewDTO.getRoleId() == 1) {
//            String message = "添加员工信息失败，非法访问";
//            log.debug(message);
//            throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
//        }
//        {
//            //调用staffMapper的countUsernameName()方法执行查询
//
//            Integer count = staffMapper.countByUsername(staffAddNewDTO.getUsername());
//            if (count > 0) {
//                String message = "添加员工信息失败，尝试使用的用户名已存在";
//                log.debug(message);
//                throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
//            }
//        }
//        {
//            //调用staffMapper的countPhone()方法执行查询
//            int count = staffMapper.countByPhone(staffAddNewDTO.getPhone());
//            if (count>0){
//                String message="添加员工信息失败，尝试使用的电话号码已存在";
//                log.debug(message);
//                throw new ServiceException(ServiceCode.ERR_CONFLICT,message);
//            }
//        }
//
//        {
//            //调用staffMapper的countEmail()方法执行查询
//            int count = staffMapper.countByEmail(staffAddNewDTO.getEmail());
//            if (count>0){
//                String message="添加员工信息失败，尝试使用的电子邮箱已被占用";
//                log.debug(message);
//                throw new ServiceException(ServiceCode.ERR_CONFLICT,message);
//            }
//        }
        //创建Staff对象
        Staff staff=new Staff();
        //复制DTO对象中的属性到实体对象中
        BeanUtils.copyProperties(staffAddNewDTO,staff);
        //设置初始登录次数
        staff.setLoginCount(0);
        //处理密码加密
        String rawPassword="123456";
        String encodedPassword=passwordEncoder.encode(rawPassword);
        staff.setPassword(encodedPassword);
        staff.setDatebirth(staff.getDatebirth().substring(0,10));
        staff.setIndatetime(staff.getIndatetime().substring(0,10));
        //调用StaffMapper的insert方法执行插入
        int rows = staffMapper.insert(staff);
        if (rows != 1) {
            String message = "添加员工失败，服务器忙，请稍后再尝试！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_INSERT, message);
        }
        // 向管理员与角色的关联表中批量插入关联数据
        StaffRole staffRole=new StaffRole();
        staffRole.setStaffId(staff.getId());
        staffRole.setRoleId(staffAddNewDTO.getRoleId());
         rows = staffRoleMapper.insert(staffRole);
        if (rows != 1) {
            String message = "添加员工失败，服务器忙，请稍后再尝试！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_INSERT, message);
        }
    }

    //删除员工帐号的业务方法
    @Override
    public void deleteById(Long id) {
        log.debug("开始处理通过Id删除员工帐号的业务");
        //判断Id是否等于1
        if (id==1){
            String message="删除员工帐号失败，尝试删除的员工不存在";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND,message);
        }
        //调用staffMapper的getStandardById方法
        StaffStandardVO standardById = staffMapper.getStandardById(id);
        //判断查询结果是否为NULL
        if (standardById==null){
            //是：抛出异常
            String message="删除员工帐号失败，尝试删除的员工不存在";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND,message);
        }
        //调用olderStaffMapper的countByStaffId()执行查询
        Integer count = olderStaffMaper.countByStaffId(id);
        if (count>0){
         String message="删除员工帐号失败，尝试删除员工与某些老人相关联";
         log.debug(message);
         throw  new ServiceException(ServiceCode.ERR_CONFLICT,message);
        }
        //调用StaffMapper的deleteById()执行删除
        int row = staffMapper.deleteById(id);
        if (row!=1){
            String message="删除员工信息失败，服务器忙请稍后尝试";
            log.debug(message);
            throw  new ServiceException(ServiceCode.ERR_DELETE,message);
        }
    }

    //启动员工帐号的业务方法
    @Override
    public void setEnable(Long id){
        setUpdateEnable(id,1);
    }
    //禁止员工帐号的业务方法
    @Override
    public void setDisable(Long id) {
        setUpdateEnable(id,0);
    }

    //查询员工列表的业务
    @Override
    public List<StaffListItemVO> list() {
        log.debug("开始执行查询员工列表的业务");
        //调用StaffMapper的list()方法查询员工列表
        List<StaffListItemVO> list = staffMapper.list();
        Iterator<StaffListItemVO> iterators = list.iterator();
        while (iterators.hasNext()){
            StaffListItemVO staffListItemVO = iterators.next();
            if (staffListItemVO.getId()==1){
                iterators.remove();
            }
        }
        return list;
    }

    private void setUpdateEnable(Long id, Integer enable){
        String[] enableTest={"禁止","启动"};
        log.debug("开始处理"+enableTest[enable]+"员工帐号的业务，参数ID：{},参数enable:{}",id,enable);
        //判断是传输过来的是否是系统管理员（院长）帐号
        if (id==1){
            //是：抛出异常
            String message=enableTest[enable]+"帐号失败，尝试"+enableTest[enable]+"帐号数据不存在";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND,message);
        }
        //调用staffMapper的getStandardById方法
        StaffStandardVO standardById = staffMapper.getStandardById(id);
        //判断查询结果是否为NULL
        if (standardById==null){
            //是：抛出异常
            String message=enableTest[enable]+"帐号失败，尝试"+enableTest[enable]+"帐号数据不存在";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND,message);
        }
       //判断设置的状态是否和原状态相同
        if (standardById.getEnable()==enable){
            //是：抛出异常
            String message=enableTest[enable]+"员工帐号失败，该帐号已处于"+enableTest[enable]+"状态";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_CONFLICT,message);
        }
        //创建Staff实体对象
        Staff staff=new Staff();
        //设置ID，设置状态
        staff.setId(id);
        staff.setEnable(enable);
        //调用staffMapper的update方法执行修改
        int rows = staffMapper.update(staff);
        if (rows!=1){
            //是：抛出异常
            String message=enableTest[enable]+"员工帐号失败，服务器忙请稍候尝试";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_UPDATE,message);
        }
    }
}
